package com.urban.app.fractal.ljapunow.activity;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import android.app.ListActivity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

import com.urban.app.fractal.ljapunow.R;

public class FileSelection extends ListActivity
{
	public static final int						MODE_CREATE			= 0;
	public static final int						MODE_OPEN			= 1;

	private static final String					ITEM_KEY			= "key";
	private static final String					ITEM_IMAGE			= "image";
	private static final String					ROOT				= "/";

	public static final String					START_PATH			= "START_PATH";
	public static final String					RESULT_PATH			= "RESULT_PATH";
	public static final String					SELECTION_MODE		= "SELECTION_MODE";
	public static final String					FILE_NAME			= "FILE_NAME";
	public static final String					TITLE				= "TITLE";

	private static String						lastPath			= null;

	private List<String>						path				= null;
	private TextView							myPath;
	private EditText							mFileName;
	private ArrayList<HashMap<String, Object>>	mList;

	private Button								selectButton;

	private LinearLayout						layoutSelect;
	private LinearLayout						layoutCreate;
	private InputMethodManager					inputManager;
	private String								parentPath;
	private String								currentPath			= ROOT;

	private int									selectionMode		= MODE_CREATE;

	private Set<String>							selectedFiles		= new HashSet<String>();
	private Set<Integer>						selectedPositions	= new HashSet<Integer>();
	private HashMap<String, Integer>			lastPositions		= new HashMap<String, Integer>();

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setResult(RESULT_CANCELED, getIntent());

		setTitle(getIntent().getStringExtra(TITLE));
		
		setContentView(R.layout.file_dialog_main);
		myPath = (TextView) findViewById(R.id.path);

		mFileName = (EditText) findViewById(R.id.fdEditTextFile);
		String fileName = getIntent().getStringExtra(FILE_NAME);
		if (fileName != null)
		{
			mFileName.setText(fileName);
		}

		inputManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);

		selectButton = (Button) findViewById(R.id.fdButtonSelect);
		selectButton.setEnabled(false);
		selectButton.setOnClickListener(new OnClickListener()
		{
			public void onClick(View v)
			{
				if (!selectedFiles.isEmpty())
				{
					getIntent().putExtra(RESULT_PATH, selectedFiles.toArray(new String[selectedFiles.size()]));
					setResult(RESULT_OK, getIntent());
					lastPath = currentPath;
					finish();
				}
			}
		});

		final Button newButton = (Button) findViewById(R.id.fdButtonNew);
		newButton.setOnClickListener(new OnClickListener()
		{
			public void onClick(View v)
			{
				setCreateVisible(v);
				mFileName.requestFocus();
			}
		});

		final Button cancelAllButton = (Button) findViewById(R.id.fdButtonCancelAll);
		cancelAllButton.setOnClickListener(new OnClickListener()
		{
			public void onClick(View v)
			{
				setResult(RESULT_CANCELED, getIntent());
				finish();
			}
		});

		selectionMode = getIntent().getIntExtra(SELECTION_MODE, MODE_CREATE);
		if (selectionMode == MODE_OPEN)
		{
			newButton.setEnabled(false);
			newButton.setVisibility(View.INVISIBLE);
		}

		layoutSelect = (LinearLayout) findViewById(R.id.fdLinearLayoutSelect);
		layoutCreate = (LinearLayout) findViewById(R.id.fdLinearLayoutCreate);
		layoutCreate.setVisibility(View.GONE);

		final Button cancelButton = (Button) findViewById(R.id.fdButtonCancel);
		cancelButton.setOnClickListener(new OnClickListener()
		{
			public void onClick(View v)
			{
				setSelectVisible(v);
			}
		});

		final Button createButton = (Button) findViewById(R.id.fdButtonCreate);
		createButton.setOnClickListener(new OnClickListener()
		{
			public void onClick(View v)
			{
				if (mFileName.getText().length() > 0)
				{
					getIntent().putExtra(RESULT_PATH, new String[] { currentPath + "/" + mFileName.getText() });
					setResult(RESULT_OK, getIntent());
					lastPath = currentPath;
					finish();
				}
			}
		});

		String startPath = getIntent().getStringExtra(START_PATH);
		if (lastPath != null)
		{
			getDir(lastPath);
		}
		else if (startPath != null)
		{
			getDir(startPath);
		}
		else
		{
			getDir(ROOT);
		}
	}

	private void getDir(String dirPath)
	{
		boolean useAutoSelection = dirPath.length() < currentPath.length();

		Integer position = lastPositions.get(parentPath);

		getDirImpl(dirPath);

		if (position != null && useAutoSelection)
		{
			getListView().setSelection(position);
		}
	}

	private class FileListAdapter extends SimpleAdapter
	{
		public FileListAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
		{
			super(context, data, resource, from, to);
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent)
		{
			if (convertView != null)
			{
				if (selectedPositions.contains(position))
				{
					setRowTextColor(convertView, Color.YELLOW);
				}
				else
				{
					setRowTextColor(convertView, Color.WHITE);
				}
			}
			return super.getView(position, convertView, parent);
		}
	}

	private void getDirImpl(final String dirPath)
	{
		currentPath = dirPath;

		final List<String> item = new ArrayList<String>();
		path = new ArrayList<String>();
		mList = new ArrayList<HashMap<String, Object>>();

		File f = new File(currentPath);
		File[] files = f.listFiles();
		if (files == null)
		{
			currentPath = ROOT;
			f = new File(currentPath);
			files = f.listFiles();
		}
		myPath.setText(getText(R.string.file_location) + ": " + currentPath);

		if (!currentPath.equals(ROOT))
		{
			item.add(ROOT);
			addItem(ROOT, R.drawable.folder);
			path.add(ROOT);

			item.add("../");
			addItem("../", R.drawable.folder);
			path.add(f.getParent());
			parentPath = f.getParent();
		}

		TreeMap<String, String> dirsMap = new TreeMap<String, String>();
		TreeMap<String, String> dirsPathMap = new TreeMap<String, String>();
		TreeMap<String, String> filesMap = new TreeMap<String, String>();
		TreeMap<String, String> filesPathMap = new TreeMap<String, String>();
		for (File file : files)
		{
			if (file.isDirectory())
			{
				String dirName = file.getName();
				dirsMap.put(dirName, dirName);
				dirsPathMap.put(dirName, file.getPath());
			}
			else
			{
				filesMap.put(file.getName(), file.getName());
				filesPathMap.put(file.getName(), file.getPath());
			}
		}
		item.addAll(dirsMap.tailMap("").values());
		item.addAll(filesMap.tailMap("").values());
		path.addAll(dirsPathMap.tailMap("").values());
		path.addAll(filesPathMap.tailMap("").values());

		FileListAdapter fileList = new FileListAdapter(this, mList, R.layout.file_dialog_row, new String[] { ITEM_KEY, ITEM_IMAGE }, new int[] { R.id.fdrowtext, R.id.fdrowimage });

		for (String dir : dirsMap.tailMap("").values())
		{
			addItem(dir, R.drawable.folder);
		}

		for (String file : filesMap.tailMap("").values())
		{
			addItem(file, R.drawable.file);
		}

		fileList.notifyDataSetChanged();

		setListAdapter(fileList);
	}

	private void addItem(String fileName, int imageId)
	{
		HashMap<String, Object> item = new HashMap<String, Object>();
		item.put(ITEM_KEY, fileName);
		item.put(ITEM_IMAGE, imageId);
		mList.add(item);
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id)
	{
		File file = new File(path.get(position));
		String fpath = file.getPath();

		if (file.isDirectory())
		{
			selectButton.setEnabled(false);
			if (file.canRead())
			{
				selectedFiles.clear();
				selectedPositions.clear();
				lastPositions.put(currentPath, position);
				getDir(path.get(position));
			}
			else
			{
				Toast.makeText(this, getString(R.string.permission_denied), Toast.LENGTH_SHORT).show();
			}
		}
		else if (selectedPositions.contains(position))
		{
			selectedFiles.remove(fpath);
			selectedPositions.remove(position);
			setRowTextColor(v, Color.WHITE);
			if (selectedFiles.isEmpty())
			{
				selectButton.setEnabled(false);
			}
		}
		else
		{
			if (selectionMode == MODE_CREATE && !selectedFiles.isEmpty())
			{
				selectedFiles.clear();
				setRowTextColor(l.getChildAt(selectedPositions.iterator().next()), Color.WHITE);
				selectedPositions.clear();
			}
			selectedFiles.add(fpath);
			selectedPositions.add(position);
			setRowTextColor(v, Color.YELLOW);
			selectButton.setEnabled(true);
		}
	}

	private void setRowTextColor(View view, int color)
	{
		TextView tv = (TextView) view.findViewById(R.id.fdrowtext);
		tv.setTextColor(color);
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		if ((keyCode == KeyEvent.KEYCODE_BACK))
		{
			selectButton.setEnabled(false);

			if (layoutCreate.getVisibility() == View.VISIBLE)
			{
				layoutCreate.setVisibility(View.GONE);
				layoutSelect.setVisibility(View.VISIBLE);
			}
			else
			{
				if (!currentPath.equals(ROOT))
				{
					getDir(parentPath);
				}
				else
				{
					return super.onKeyDown(keyCode, event);
				}
			}

			return true;
		}
		else
		{
			return super.onKeyDown(keyCode, event);
		}
	}

	private void setCreateVisible(View v)
	{
		layoutCreate.setVisibility(View.VISIBLE);
		layoutSelect.setVisibility(View.GONE);

		inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
		selectButton.setEnabled(false);
	}

	private void setSelectVisible(View v)
	{
		layoutCreate.setVisibility(View.GONE);
		layoutSelect.setVisibility(View.VISIBLE);

		inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
		selectButton.setEnabled(false);
	}
}
